use std::sync::atomic::{AtomicI64, AtomicU64, Ordering};
use std::sync::Arc;
use lazy_static::lazy_static;
use chrono::{DateTime, Utc};
use prometheus::{Encoder, TextEncoder, IntGauge, IntCounter, Registry};

#[derive(Default)]
pub struct MetricsCollector {
    active_nodes: AtomicI64,
    total_nodes: AtomicI64,
    commands_total: AtomicU64,
    commands_success: AtomicU64,
    commands_failed: AtomicU64,
    file_transfers_total: AtomicU64,
    file_transfer_bytes: AtomicU64,
    last_heartbeat: AtomicU64,
}

impl MetricsCollector {
    pub fn new() -> Self {
        Self::default()
    }
    
    // 节点指标
    pub fn update_node_metrics(&self, active: i64, total: i64) {
        self.active_nodes.store(active, Ordering::Relaxed);
        self.total_nodes.store(total, Ordering::Relaxed);
    }
    
    pub fn get_active_nodes(&self) -> i64 {
        self.active_nodes.load(Ordering::Relaxed)
    }
    
    pub fn get_total_nodes(&self) -> i64 {
        self.total_nodes.load(Ordering::Relaxed)
    }
    
    // 命令指标
    pub fn increment_commands_total(&self) {
        self.commands_total.fetch_add(1, Ordering::Relaxed);
    }
    
    pub fn increment_commands_success(&self) {
        self.commands_success.fetch_add(1, Ordering::Relaxed);
    }
    
    pub fn increment_commands_failed(&self) {
        self.commands_failed.fetch_add(1, Ordering::Relaxed);
    }
    
    pub fn get_commands_total(&self) -> u64 {
        self.commands_total.load(Ordering::Relaxed)
    }
    
    pub fn get_commands_success(&self) -> u64 {
        self.commands_success.load(Ordering::Relaxed)
    }
    
    pub fn get_commands_failed(&self) -> u64 {
        self.commands_failed.load(Ordering::Relaxed)
    }
    
    // 文件传输指标
    pub fn increment_file_transfers_total(&self) {
        self.file_transfers_total.fetch_add(1, Ordering::Relaxed);
    }
    
    pub fn add_file_transfer_bytes(&self, bytes: u64) {
        self.file_transfer_bytes.fetch_add(bytes, Ordering::Relaxed);
    }
    
    pub fn get_file_transfers_total(&self) -> u64 {
        self.file_transfers_total.load(Ordering::Relaxed)
    }
    
    pub fn get_file_transfer_bytes(&self) -> u64 {
        self.file_transfer_bytes.load(Ordering::Relaxed)
    }
    
    // 心跳指标
    pub fn record_node_heartbeat(&self, timestamp: DateTime<Utc>) {
        self.last_heartbeat.store(timestamp.timestamp() as u64, Ordering::Relaxed);
    }
    
    pub fn get_last_heartbeat(&self) -> DateTime<Utc> {
        let timestamp = self.last_heartbeat.load(Ordering::Relaxed);
        DateTime::from_timestamp(timestamp as i64, 0).unwrap_or_else(|| Utc::now())
    }
    
    // 获取所有指标
    pub fn get_all_metrics(&self) -> serde_json::Value {
        serde_json::json!({
            "nodes": {
                "active": self.get_active_nodes(),
                "total": self.get_total_nodes()
            },
            "commands": {
                "total": self.get_commands_total(),
                "success": self.get_commands_success(),
                "failed": self.get_commands_failed()
            },
            "file_transfers": {
                "total": self.get_file_transfers_total(),
                "bytes": self.get_file_transfer_bytes()
            },
            "heartbeat": {
                "last": self.get_last_heartbeat().to_rfc3339()
            }
        })
    }

    // 导出为 Prometheus 文本格式
    pub fn encode_prometheus(&self) -> String {
        let registry = Registry::new();

        // 定义指标
        let g_active_nodes = IntGauge::new("cluster_active_nodes", "Number of active nodes").unwrap();
        let g_total_nodes = IntGauge::new("cluster_total_nodes", "Total number of nodes").unwrap();

        let c_commands_total = IntCounter::new("commands_total", "Total commands").unwrap();
        let c_commands_success = IntCounter::new("commands_success", "Successful commands").unwrap();
        let c_commands_failed = IntCounter::new("commands_failed", "Failed commands").unwrap();

        let c_file_transfers_total = IntCounter::new("file_transfers_total", "Total file transfers").unwrap();
        let c_file_transfer_bytes = IntCounter::new("file_transfer_bytes", "File transfer bytes").unwrap();

        // 注册
        registry.register(Box::new(g_active_nodes.clone())).ok();
        registry.register(Box::new(g_total_nodes.clone())).ok();
        registry.register(Box::new(c_commands_total.clone())).ok();
        registry.register(Box::new(c_commands_success.clone())).ok();
        registry.register(Box::new(c_commands_failed.clone())).ok();
        registry.register(Box::new(c_file_transfers_total.clone())).ok();
        registry.register(Box::new(c_file_transfer_bytes.clone())).ok();

        // 赋值/累加
        g_active_nodes.set(self.get_active_nodes());
        g_total_nodes.set(self.get_total_nodes());
        c_commands_total.inc_by(self.get_commands_total() as u64);
        c_commands_success.inc_by(self.get_commands_success() as u64);
        c_commands_failed.inc_by(self.get_commands_failed() as u64);
        c_file_transfers_total.inc_by(self.get_file_transfers_total() as u64);
        c_file_transfer_bytes.inc_by(self.get_file_transfer_bytes() as u64);

        // 编码
        let metric_families = registry.gather();
        let mut buf = Vec::new();
        let encoder = TextEncoder::new();
        let _ = encoder.encode(&metric_families, &mut buf);
        String::from_utf8(buf).unwrap_or_default()
    }
} 

lazy_static! {
    pub static ref METRICS: Arc<MetricsCollector> = Arc::new(MetricsCollector::new());
}